#pragma once
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
#include <cassert>
#include <fstream>
#include <mutex>
#include <jsoncpp/json/json.h>
#include "../comm/util.hpp"
#include "../comm/log.hpp"

namespace ns_model
{
    using namespace ns_log;
    struct Question
    {
        std::string id; // 题目编号
        std::string name; // 题目名称
        std::string level; // 题目难度
        int cpu_limit; // 时间限制（单位：s）
        int mem_limit; // 内存限制（单位：KB）
        std::string desc; // 文件描述
        std::string header; // 文件头
        std::string tail; // 文件尾
    };

    class Model
    {
    public:
        Model()
        {
            assert(LoadQuestionList());
        }

        ~Model()
        {}

    public:
        bool LoadOneQuestion(const std::string& id, Question* q)
        {
            const auto& it = questions.find(id);
            if(it == questions.end()) return false;
            *q = it->second;
            LOG(INFO) << "题目:" << q->id << " 加载成功\n";
            return true;
        }

        bool LoadAllQuestion(std::vector<Question>* v)
        {
            if(questions.empty()) return false;
            for(const auto& x : questions)
            {
                (*v).push_back(x.second);
            }
            LOG(INFO) << "成功加载所有题目\n";
            return true;
        }

    private:
        const std::string question_list = "./questions/questions.list"; // 题目列表路径
        const std::string question_path = "./questions/"; // 题目路径
        std::unordered_map<std::string, Question> questions; // 所有题目信息

    private:
        bool LoadQuestionList()
        {
            // 将所有题目信息加载到questions
            std::ifstream in(question_list); 
            if(!in.is_open())
            {
                LOG(FATAL) << "question_list加载失败\n";
                return false;
            }

            std::string line;
            while(std::getline(in, line)) // 获取question_list每一行
            {
                if(line.empty()) continue;
                std::vector<std::string> tokens; // 保存每一行的单个信息
                ns_util::FileUtil::StringSplit(line, tokens, " ");
                if(tokens.size() != 5)
                {
                    LOG(FATAL) << "question_list信息有误\n";
                    return false;
                }

                Question q; // 1 回文数 简单 1 30000
                q.id = tokens[0];
                q.name = tokens[1];
                q.level = tokens[2];
                q.cpu_limit = atoi(tokens[3].c_str());
                q.mem_limit = atoi(tokens[4].c_str());
                ns_util::FileUtil::ReadFile(question_path + q.id + "/desc.txt", q.desc, true);
                ns_util::FileUtil::ReadFile(question_path + q.id + "/header.cc", q.header, true);
                ns_util::FileUtil::ReadFile(question_path + q.id + "/tail.cc", q.tail, true);

                questions.insert({q.id, q}); // 插入到哈希表中
            }

            in.close();

            LOG(INFO) << "题目信息加载成功\n";
            return true;
        }
    };
}